#include "RTPSharePictureImpl.hpp"
#include "SharedMemory.hpp"

#include <string>

static const char* YUC_SHARE_PATH_SUFFIX = "_yuv";
static const char* BGR_SHARE_PATH_SUFFIX = "_bgr";

static const uint32_t SHARE_MEMORY_EXTEND_LEN = 32;

using namespace std;

RTPSharePictureImpl::~RTPSharePictureImpl() {
	this->Stop();
}

bool RTPSharePictureImpl::Start(const char* sharePath, uint32_t width, uint32_t height) {
	
	this->yuvMemory = CreateYUVShareMemory(sharePath, width, height);
	if (nullptr == this->yuvMemory) {
		return false;
	}
	
	this->bgrMemory = CreateBGRShareMemory(sharePath, width, height);
	if (nullptr == this->bgrMemory) {
		if (this->yuvMemory != nullptr) {
			delete this->yuvMemory;
			this->yuvMemory = nullptr;
		}
		return false;
	}

	bgrShareProxy.Start(width, RTPSharePictureImpl::GetBGRSize(width, height), 
		[&](const uint8_t* bgr, uint32_t shareSize){
			if (this->bgrMemory) {
				this->bgrMemory->Write(bgr, shareSize);
			}
		});

	yuvShareProxy.Start(width, RTPSharePictureImpl::GetYUVSize(width, height), 
		[&](const uint8_t* yuv, uint32_t shareSize){      
			if (this->yuvMemory) {
				this->yuvMemory->Write(yuv, shareSize);
			}
		});
	
	return true;
}

SharedMemory* RTPSharePictureImpl::CreateYUVShareMemory(const char* sharePath, uint32_t width, uint32_t height) {
	string yuvPath = sharePath;
	yuvPath += YUC_SHARE_PATH_SUFFIX;
	uint32_t yuvSize = RTPSharePictureImpl::GetYUVSize(width, height);
	uint32_t yuvShareSize = yuvSize + SHARE_MEMORY_EXTEND_LEN;
	
	SharedMemory* memory = new SharedMemory();
	auto ret = memory->Init(yuvPath.c_str(), yuvShareSize, true);
	if (!SharedMemory::IsSuccess(ret)) {
		delete memory;
		memory = nullptr;
		return nullptr;
	}
	return memory;
}


SharedMemory* RTPSharePictureImpl::CreateBGRShareMemory(const char* sharePath, uint32_t width, uint32_t height) {
	string bgrPath = sharePath;
	bgrPath += BGR_SHARE_PATH_SUFFIX;
	
	uint32_t bgrSize = RTPSharePictureImpl::GetBGRSize(width, height);
	uint32_t bgrShareSize = bgrSize + SHARE_MEMORY_EXTEND_LEN;
	SharedMemory* memory = new SharedMemory();
	auto ret = memory->Init(bgrPath.c_str(), bgrShareSize, true);
	if (!SharedMemory::IsSuccess(ret)) {
		delete memory;
		memory = nullptr;
		return nullptr;
	}
	return memory;
}

void RTPSharePictureImpl::OnYUV(const uint8_t* data, size_t len, uint32_t width, uint32_t height, void*) {
	if (nullptr == this->yuvMemory) {
		return;
	}
	yuvShareProxy.OnPic(data, width, height);
}

void RTPSharePictureImpl::OnRGB(const uint8_t* data, size_t len, uint32_t width, uint32_t height, void*) {
	if (nullptr == this->bgrMemory) {
		return;
	}
	bgrShareProxy.OnPic(data, width, height);
}

void RTPSharePictureImpl::Stop() {
	bgrShareProxy.Stop();
	yuvShareProxy.Stop();

	if (this->yuvMemory) {
		delete this->yuvMemory;
		this->yuvMemory = nullptr;
	}
	
	if (this->bgrMemory) {
		delete this->bgrMemory;
		this->bgrMemory = nullptr;
	}	
}